import asyncio
from typing import Optional

from fastapi.encoders import jsonable_encoder
from starlette.responses import StreamingResponse, JSONResponse
import datetime
from pojo.response import Response
from service import dataService
from service.strategyService import Chip
from fastapi import APIRouter, Query
import pandas as pd
from service.strategyService import Movement
from utils.utils import is_empty

strategyRouter = APIRouter(tags=['data'])

@strategyRouter.get('/select/LowIntensiveChipStrategy',
                    summary='低位单峰密集筹码选股',
                    description='流式传输')
async def select_LowIntensiveChipStrategy(
    num: str = Query(description='选股数量'),
    window: str = Query(description='时间窗口'),
    profit_rate: Optional[str] = Query(None, description='收益率'),
    concentration_90: Optional[str] = Query(None, description='90集中度'),
    concentration_70: Optional[str] = Query(None, description='70集中度')
):
    # 参数处理
    if isinstance(num, str):
        if is_empty(num):
            return Response(
                code=0,
                message='参数错误! 选股数量不能为空'
            )
        else:
            num = int(num)

    if isinstance(window, str):
        if is_empty(window):
            return Response(
                code=0,
                message='参数错误! 时间窗口不能为空'
            )
        else:
            window = int(window)

    if isinstance(profit_rate, str):
        if is_empty(profit_rate):
            profit_rate = None
        else:
            profit_rate = float(profit_rate.strip())

    if isinstance(concentration_90, str):
        if is_empty(concentration_90):
            concentration_90 = None
        else:
            concentration_90 = float(concentration_90.strip())

    if isinstance(concentration_70, str):
        if is_empty(concentration_70):
            concentration_70 = None
        else:
            concentration_70 = float(concentration_70.strip())

    async def event_stream():
        n = 0

        _, stockInfo_df = await dataService.get_stockInfoList()
        model = Chip.LowIntensiveChipStrategy(profit_rate=profit_rate, concentration_90=concentration_90,
                                              concentration_70=concentration_70)
        for index, row in pd.DataFrame(stockInfo_df).iterrows():
            code = row['code']
            _, df = await dataService.get_stockChipList(
                code=code,
                window=window,
            )

            print(f'正在分析筹码数据,code:{code}')

            if df is None:
                continue

            if model.select(data=df):
                print('结果为True')
                response = Response(
                    code=1,
                    message='已选出一个低峰密集型筹码',
                    data=f'{code}'
                )
                yield f"data: {response.model_dump_json()}\n\n"
                n += 1
                if n >= num:
                    break

            else:
                print('结果为False')

    return StreamingResponse(event_stream(), media_type='text/event-stream')

@strategyRouter.get('/analyze/IntradayMovementStrategy',
                    summary='日内动量分析策略',
                    description='返回代表上下边界的坐标点列表')
async def analyze_IntradayMovementStrategy(
        code: str = Query(description='股票代码'),
        window: Optional[str] = Query('14', description='时间窗口, 默认为14天'),
        period: Optional[str] = Query('15', description='周期, 默认为15分钟 可选15 30')
):
    if isinstance(code, str) and is_empty(code):
        return Response(
            code=0,
            message="参数错误: 股票代码(code)参数不能为空!"
        )

    # 处理参数
    if isinstance(window, str):
        if is_empty(window):
            window = 14
        else:
            window = int(window)


    # 默认值
    if isinstance(period, str) and is_empty(period):
        period = '15'

    # 获得日内动量数据
    model = Movement.IntradayMovementStrategy(period=period, window=window, code=code)
    async def event_stream():
        # 进行日内动量交易监测
        current_time = datetime.datetime.now()
        # 返回之前时间间隔内的分析数值
        _, hist_df = await dataService.get_stockHistList(
            code=code,
            start_date=current_time.strftime('%Y%m%d'),
            end_date=current_time.strftime('%Y%m%d'),
            period=period
        )
        # 时间段内没数据, 不是交易日
        if hist_df is None:
            return

        # 填充字段
        hist_df['time'] = hist_df.index.time
        hist_df['news'] = hist_df['close']
        for _, row in hist_df.iterrows():
            data = await model.apply(row)
            if data is None:
                break
            # 构造响应
            response = Response(
                code=1,
                message='日内动量监测成功',
                data={
                    'news': data['news'],
                    'vmap': data['vmap'],
                    'time': data['time'].strftime('%H:%M:%S'),  # ⚠️ 注意时间类型必须转字符串
                    'signal': data['signal'],
                }
            )
            yield f"data: {response.model_dump_json()}\n\n"

        # 正点监测
        while True:
            # 获得最新数据
            current_time = datetime.datetime.now()
            _, hist_df = await dataService.get_stockHistList(
                code=code,
                start_date=current_time.strftime('%Y%m%d'),
                end_date=current_time.strftime('%Y%m%d'),
                period=period
            )
            # 时间段内没数据, 不是交易日
            if hist_df is None:
                return

            # 填充字段
            hist_df['time'] = hist_df.index.time
            hist_df['news'] = hist_df['close']
            # 比较time
            minute = current_time.minute
            if minute % int(period) == 0 and hist_df.loc[-1]['time'] == current_time:
                data = await model.apply(hist_df)
                if data is None:
                    break
                    # 构造响应
                response = Response(
                    code=1,
                    message='日内动量监测成功',
                    data={
                        'news': data['news'],
                        'vmap': data['vmap'],
                        'time': data['time'].strftime('%H:%M:%S'),  # ⚠️ 注意时间类型必须转字符串
                        'signal': data['signal'],
                    }
                )
                yield f"data: {response.model_dump_json()}\n\n"
            # 每一分钟循环一次
            await asyncio.sleep(60)

    return StreamingResponse(event_stream(), media_type='text/event-stream')



